001    package net.sf.xdc.util;
002    
003    /*
004     *  Copyright 2005-2006 Jens Voß.
005     *
006     *  Licensed under the GNU Lesser General Public License (the "License");
007     *  you may not use this file except in compliance with the License.
008     *  You may obtain a copy of the License at
009     *
010     *       http://opensource.org/licenses/lgpl-license.php
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    
019    import java.io.File;
020    import java.io.FileReader;
021    import java.io.IOException;
022    import java.io.Reader;
023    import java.util.List;
024    import java.util.Vector;
025    
026    /**
027     * A <code>FileTokenizer</code> is used to parse an options file for the XDC
028     * tool (which is specified with the '@' notation as a command line argument).
029     *
030     * @author Jens Voß
031     * @since 0.5
032     * @version 0.5
033     */
034    public class FileTokenizer {
035    
036      private File file;
037    
038      /**
039       * Public constructor.
040       *
041       * @param file The file containing the XDC options
042       */
043      public FileTokenizer(File file) {
044        this.file = file;
045      }
046    
047      /**
048       * This method does the actual parsing of the XDC options file. It breaks up
049       * the contents into tokens. The following rules apply:
050       * <ol>
051       *   <li>Every character may be escaped by placing a backslash ('\') in front
052       *       of it.</li>
053       *   <li>Text starting with an (not escaped) hash sign ('#') and ending with a
054       *       line terminator is considered a comment and is ignored.
055       *   <li>Text enclosed by double quotes is considered a single token. (The
056       *       quotes will be stripped by this method.)</li>
057       *   <li>All whitespace characters (i.e. spaces, tabs, line terminators etc.)
058       *       which are neither escaped nor part of a comment nor part of a quoted
059       *       token are treated as token delimiters.
060       * </ol>
061       *
062       * @return An array of the individual tokens contained in this file
063       * @throws IOException
064       */
065      public String[] getContents() throws IOException {
066        List retVal = new Vector();
067        Reader in = null;
068        try {
069          in = new FileReader(file);
070          boolean hash = false;
071          boolean quot = false;
072          StringBuffer buf = new StringBuffer();
073          char c;
074          while ((c = (char) in.read()) != (char) -1) {
075            if (hash) {
076              if (c == '\n' || c == '\r') {
077                hash = false;
078              }
079            }
080            else if (c == '#') {
081              if (!quot) {
082                String str = buf.toString().trim();
083                if (str.length() > 0) {
084                  retVal.add(str);
085                }
086                buf.setLength(0);
087              }
088              hash = true;
089            }
090            else if (c == '\\') {
091              buf.append((char) in.read());
092            }
093            else if (quot) {
094              if (c == '"') {
095                quot = false;
096                String str = buf.toString().trim();
097                if (str.length() > 0) {
098                  retVal.add(str);
099                }
100                buf.setLength(0);
101              }
102              else {
103                buf.append(c);
104              }
105            }
106            else if (c == '"') {
107              quot = true;
108              String str = buf.toString().trim();
109              if (str.length() > 0) {
110                retVal.add(str);
111              }
112              buf.setLength(0);
113            }
114            else if (Character.isWhitespace(c)) {
115              String str = buf.toString().trim();
116              if (str.length() > 0) {
117                retVal.add(str);
118              }
119              buf.setLength(0);
120            }
121            else {
122              buf.append(c);
123            }
124          }
125          String str = buf.toString().trim();
126          if (str.length() > 0) {
127            retVal.add(str);
128          }
129          return (String[]) retVal.toArray(new String[retVal.size()]);
130        }
131        finally {
132          if (in != null) {
133            try {
134              in.close();
135            }
136            catch (IOException e) {
137              e.printStackTrace();
138            }
139          }
140        }
141      }
142    
143    }